package com.free.semantic.core.takeclient.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.free.semantic.common.BaseNode;
import com.free.semantic.common.RangeObj;
import com.free.semantic.core.ConceptInstanceManage;
import com.free.semantic.core.script.SemanticNetEngine;
import com.free.semantic.core.script.impl.ScriptEngineImpl;
import com.free.semantic.core.takeclient.ConceptInsTakeCommand;
import okhttp3.*;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

public class UrlClientImpl implements ConceptInsTakeCommand {

    private String url;

    private ConceptInstanceManage instanceManage;

    private OkHttpClient client;

    public UrlClientImpl(String clientUrl) {
        this.url = clientUrl;
        if (!url.endsWith("/")) {
            url = url + "/";
        }
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[]{};
            }
        }};

        // 创建 SSLContext 并使用 TrustManager 初始化
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

            // 创建 OkHttpClient 并设置 SSLContext
            client = new OkHttpClient.Builder().sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0]).hostnameVerifier((hostname, session) -> true) // 忽略主机名验证
                    .build();
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            e.printStackTrace();
        }
    }

    public UrlClientImpl(ConceptInstanceManage instanceManage, String clientUrl) {
        this.instanceManage = instanceManage;
        this.url = clientUrl;
    }

    public <T> T getValue(String script) {
        SemanticNetEngine engine = new ScriptEngineImpl();
        return engine.execScript(instanceManage, String.format("%s,%s", url, script));
    }

    private List<String> sendGet(List<? extends BaseNode> nodes, RangeObj dest) throws NoSuchAlgorithmException {
        JSONObject json = new JSONObject();
        json.put("from", nodes);
        json.put("destObject", dest.getObjectName());
        String string = json.toString();
        RequestBody body = RequestBody.create(string,
                MediaType.parse("application/json; charset=utf-8")
        );
        // 创建请求对象
        Request request = new Request.Builder().url(url) // 替换为你要请求的URL
                .post(body).build();
        // 发起请求并处理响应
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful() && response.body() != null) {
                // 打印响应体
                String responseBody = response.body().string();
                JSONObject jsonObject = JSONObject.parseObject(responseBody);
                List<String> resLs = new ArrayList<>();
                if (!jsonObject.getBoolean("success")) {
                    throw new RuntimeException("rpc failed: " + jsonObject.getString("errorMessage"));
                }
                JSONArray result = jsonObject.getJSONArray("result");
                for (Object o : result) {
                    resLs.add(o.toString());
                }
                return resLs;
            } else {
                throw new RuntimeException("Request failed with code: " + response.code());
            }
        } catch (IOException e) {
            throw new RuntimeException(e.getCause());
        }
    }

    @Override
    public <T> List<T> take(List<BaseNode> nodes, RangeObj dest) {
        if (instanceManage != null) {
            return instanceManage.goByLocatorNode(nodes, dest);
        } else {
            try {
                return (List<T>) sendGet(nodes, dest);
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e.getCause());
            }
        }
    }
}
